package com.gugu.procedure.service;


import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.gugu.procedure.bean.*;
import com.gugu.procedure.common.Constant;
import com.gugu.procedure.common.MessageResult;
import com.gugu.procedure.dao.*;
import com.gugu.procedure.exceptions.BusinessException;
import com.gugu.procedure.util.*;
import com.gugu.procedure.vo.OrderItemProductionRecordVo;
import com.gugu.procedure.vo.OrderProductionRecordVo;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ProductionRecordService {

    @Autowired
    private ProductionRecordDao productionRecordDao;
    @Autowired
    private ProductionDao productionDao;
    @Autowired
    private ProductionService productionService;
    @Autowired
    private OrderItemDao orderItemDao;

    @Autowired
    private InsideOrderService insideOrderService;
    @Autowired
    private OrderProductionRecordDao orderProductionRecordDao;
    @Autowired
    private StaffDao staffDao;
    @Autowired
    private ReplenishmentDao replenishmentDao;


    public List <String> queryBackNumber(String orderNo, String specs, String staffName, String production, Integer num) {
        return productionRecordDao.queryBackNumber(orderNo, specs, staffName, production, num);
    }


    public ProductionRecord queryByOrderNoAndNumberAndProduction(String orderNo, String number) {
        return productionRecordDao.findTopByOrderNoAndNumberAndStatusOrderByIdDesc(orderNo, number, Constant.STATUS_1);
    }

    public List <ProductionRecord> findByWorkDoneId(Long workDoneId) {
        return productionRecordDao.findByWorkDoneId(workDoneId);
    }


    public MessageResult listProduction() {
        List <String> list = productionRecordDao.listProduction();
        return MessageResult.getSuccessInstance(list);
    }

    public void update(ProductionRecord productionRecord) {
        productionRecordDao.save(productionRecord);
    }

    // 保存流转工序记录
    @Transactional
    public MessageResult save(ProductionRecord productionRecord, String tag, boolean replenishmentFlag) {
        // 如果当前保存的状态与下一个状态不一致 则给出提示
        String time = DateUtil.getFormatedDateTime();
        ProductionRecord bean = productionRecordDao.
                findTopByOrderNoAndNumberAndProductionAndNgTagOrderByIdDesc(productionRecord.getOrderNo(), productionRecord.getNumber(),
                        productionRecord.getProduction());
        // 如果该模具处于补料申请中  则不允许进行提交
        if (!replenishmentFlag) {
            if (Objects.nonNull(bean) && StringUtil.equals(bean.getStatus(), Constant.PRODUCTION_RECORD_2)) {
                return new MessageResult(100, "当前产品处于补料申请中,不能进行流转");
            }
            String s = queryProductionRecordByOrderNoAndNumber(productionRecord.getOrderNo(), productionRecord.getNumber());
            if (StringUtil.notEquals(s, productionRecord.getProduction() + "-" + tag)) {
                return new MessageResult(100, "模具编号" + productionRecord.getNumber() + "流转工艺为：" + s);
            }
        }

        if (Constant.PRODUCTION_RECORD_TAG_START.equals(tag)) {
            bean = productionRecord;
            bean.setStartTime(time);
        } else {
            if (bean == null) {
                return new MessageResult(100, "请确认模具编号" + productionRecord.getNumber() + "流转工艺为：" + productionRecord.getProduction() + "是否已经报送开始工序");
            }
            bean.setEndTime(time);
        }
        // 设置日期字段
        if (StringUtil.isNotEmpty(bean.getStartTime())) {
            bean.setStartDate(DateUtil.parseStrToDate(bean.getStartTime(), DateUtil.DATE_FORMAT));
        }
        productionRecordDao.save(bean);
        // 处理订单的流程信息
        //  如果tag等于开始  则需要判断是否该订单当前工艺的开始时间记录 有则不进行处理  没有 则记录该订单的当前工艺的开始时间
        if (Constant.PRODUCTION_RECORD_TAG_START.equals(tag)) {
            OrderProductionRecord orderProductionRecord = orderProductionRecordDao.findTopByOrderNoAndProductionAndStatus(productionRecord.getOrderNo(), productionRecord.getProduction(),
                    Constant.STATUS_1);
            if (Objects.isNull(orderProductionRecord)) {
                orderProductionRecord = new OrderProductionRecord();
                orderProductionRecord.setStatus(Constant.STATUS_1);
                orderProductionRecord.setOrderNo(productionRecord.getOrderNo());
                orderProductionRecord.setProduction(productionRecord.getProduction());
                orderProductionRecord.setStartTime(time);
                orderProductionRecord.setSpecs(productionRecord.getSpecs());
                orderProductionRecordDao.save(orderProductionRecord);
            }

            String finalProduction = productionService.finalProduction(productionRecord.getOrderNo(), productionRecord.getSpecs());
            // 如果当前工序是品管 则需要将之前的工艺状态为4 或者5 的置位6
            if (finalProduction.equals(productionRecord.getProduction())) {
                List <String> status = new ArrayList <>();
                status.add(Constant.PRODUCTION_RECORD_4);
                status.add(Constant.PRODUCTION_RECORD_5);
                List <ProductionRecord> productionRecords = productionRecordDao.findByOrderNoAndNumberAndStatusIn(productionRecord.getOrderNo(), productionRecord.getNumber(), status);
                for (ProductionRecord productionRecord1 : productionRecords) {
                    productionRecord1.setStatus(Constant.PRODUCTION_RECORD_6);
                }
                productionRecordDao.saveAll(productionRecords);
            }

        } else {
            // 如果tag=结束 则需要判断是否是最后的一个模具编号 是 则记录该订单当前工艺的结束时间 不是则不进行处理
            if (checkProductionFinish(productionRecord.getOrderNo(), productionRecord.getProduction())) {
                OrderProductionRecord orderProductionRecord = orderProductionRecordDao.findTopByOrderNoAndProductionAndStatus(productionRecord.getOrderNo(), productionRecord.getProduction(),
                        Constant.STATUS_1);
                if (Objects.isNull(orderProductionRecord)) {
                    orderProductionRecord = new OrderProductionRecord();
                    orderProductionRecord.setStatus(Constant.STATUS_1);
                }
                orderProductionRecord.setEndTime(time);
                orderProductionRecord.setSpecs(productionRecord.getSpecs());
                orderProductionRecordDao.saveAndFlush(orderProductionRecord);
            }

            //判断整个订单是否已完成
            List <OrderProductionRecord> list1 = orderProductionRecordDao.findAllByOrderNoAndStatus(productionRecord.getOrderNo(), Constant.STATUS_1);
            List <String> list2 = productionDao.findProcedures(productionRecord.getOrderNo());
            List <String> list3 = new ArrayList <>(); //存储了整个订单设计的工艺流程
            for (String s : list2) {
                List <String> list = JsonUtil.decodeJsonToList(s, String.class);
                for (String ss : list) {
                    if (!list3.contains(ss)) {
                        list3.add(ss);
                    }
                }
            }
            // 如果list3中所有的工艺 list1中记录都有 则说明整个订单的工艺都完成了
            boolean finishFlag = true;
            for (String sss : list3) {
                boolean flag1 = false;
                for (OrderProductionRecord orderProductionRecord : list1) {
                    if (orderProductionRecord.getProduction().equals(sss)) {
                        flag1 = true;
                    }
                }
                if (!flag1) {
                    finishFlag = false;
                }
            }
            // 订单完成
            if (finishFlag) {
                InsideOrder insideOrder = insideOrderService.queryInsideOrderByOrderNo(productionRecord.getOrderNo());
                insideOrder.setStatus(Constant.ORDER_STATUS_4);
                insideOrderService.updateInsideOrder(insideOrder);
            }

            //  处理品管回退
            List <String> productions = productionService.productions(productionRecord.getOrderNo(), productionRecord.getSpecs());
            String production = productionRecord.getProduction();
            boolean addFlag = false;
            int index = -1;
            for (int i = 0; i < productions.size(); i++) {
                String s = productions.get(i);
                if (production.equals(s)) {
                    addFlag = true;
                    index = i + 1;
                }
                if (0 <= index && index < productions.size()) {
                    for (int k = index; k < productions.size(); k++) {
                        String p = productions.get(k);
                        ProductionRecord p2 = productionRecordDao.findTopByOrderNoAndNumberAndProductionAndStatusAndEndTimeNotNull(
                                productionRecord.getOrderNo(), productionRecord.getNumber(), p, Constant.PRODUCTION_RECORD_5);
                        if (p2 != null) {
                            ProductionRecord newProductionRecord = new ProductionRecord();
                            BeanUtil.copyProperties(p2, newProductionRecord);
                            newProductionRecord.setStartTime(DateUtil.getFormatedDateTime());
                            newProductionRecord.setEndTime(DateUtil.getFormatedDateTime());
                            newProductionRecord.setId(null);
                            newProductionRecord.setStatus(Constant.PRODUCTION_RECORD_1);
                            newProductionRecord.setRemark("重新回显");
                            productionRecordDao.save(newProductionRecord);
                        } else {
                            return MessageResult.success();
                        }
                    }

                }
            }
        }
        return MessageResult.success();
    }

    //查询某个订单的某个工艺有多少个产品
    public boolean checkProductionFinish(String orderNo, String production) {
        int factNum = productionDao.queryProductNumByOrderNoAndProduction(orderNo, "%" + production + "%");
        int finishNum = productionRecordDao.countProductionRecord(orderNo, production, Constant.STATUS_1);
        return factNum == finishNum;
    }

    // 根据订单查询流转工序


    // 查询某个产品的工序流程
    public String queryProductionRecordByOrderNoAndNumber(String orderNo, String number) {
        InsideOrder insideOrder = insideOrderService.queryInsideOrderByOrderNo(orderNo);
        if (Objects.isNull(insideOrder)) {
            throw new BusinessException("订单【" + orderNo + "】不存在");
        }
        // TODO 状态判断
        OrderItem orderItem = insideOrderService.queryOrderItemByOrderNoAndNumber(orderNo, number);
        if (Objects.isNull(orderItem)) {
            throw new BusinessException("请检查订单【" + orderNo + "】参数表是否已上传");
        }
        ProductionRecord productionRecord = productionRecordDao.findTopByOrderNoAndNumberAndStatusOrderByIdDesc(orderNo, number, Constant.PRODUCTION_RECORD_1);
        String nextProduction = nextProductionRecord(productionRecord, orderNo, orderItem.getSpecs());
        return nextProduction;

    }

    /**
     * 获取其下一个工艺
     * 1、需要考虑第一个工艺
     * 2、需要考虑整个流程已经完成的情况
     */

    public String nextProductionRecord(ProductionRecord productionRecord, String orderNo, String specs) {
        // 开始流转  即第一个工艺开始
        Production production = productionDao.findTopByOrderNoAndSpecs(orderNo, specs);
        if (Objects.isNull(production) || Objects.isNull(production.getProcedures())) {
            throw new BusinessException("请检查该订单参数表是否已上传");
        }
        List <String> list = (List) JSONUtils.parse(production.getProcedures());
        if (productionRecord == null) {
            return list.get(0) + "-开始";
        } else {
            for (int i = 0; i < list.size(); i++) {
                if (StringUtil.equals(productionRecord.getProduction(), list.get(i))) {
                    // 说明已经完成了
                    if (i == list.size() - 1) {
                        if (StringUtil.isEmpty(productionRecord.getEndTime())) {
                            return productionRecord.getProduction() + "-" + Constant.PRODUCTION_RECORD_TAG_END;
                        } else {
                            return "已完成";
                        }
                    } else {
                        if (StringUtil.isNotEmpty(productionRecord.getStartTime()) && StringUtil.isEmpty(productionRecord.getEndTime())) {
                            return productionRecord.getProduction() + "-" + Constant.PRODUCTION_RECORD_TAG_END;
                        } else {
                            return list.get(i + 1) + "-" + Constant.PRODUCTION_RECORD_TAG_START;
                        }
                    }
                }
            }
        }
        return "未知";
    }

    // 修理品订单使用
    public List <Map <String, Object>> orderItemUpdateProductionRecord(String orderNo, String production) {
        List <Map <String, Object>> mapList = productionRecordDao.queryListForUpdate(orderNo, production);
        return mapList;
    }

    //新品订单使用
    public Map <String, Object> orderItemProductionRecord(String orderNo, String production, String number, String specs, int pageNo, int pageSize) {
        Map <String, Object> map = new HashedMap();
        List <OrderItemProductionRecordVo> voList = new ArrayList <>();
        // 这里将所有的模具编号都返回回来了 所以在这里进行分页处理
        List <OrderItem> list = this.listOrderItemByOrderNoAndProduction(orderNo, production);
        if (StringUtil.isNotEmpty(number)) {
            list = list.stream().filter(bean -> bean.getNumberStart().equals(number)).collect(Collectors.toList());
        }
        if (StringUtil.isNotEmpty(specs)) {
            list = list.stream().filter(bean -> bean.getSpecs().equals(specs)).collect(Collectors.toList());
        }
        map.put("count", list.size());
        list = pageOrderItem(list, number, specs, pageNo, pageSize);
        List <ProductionRecord> productionRecords = productionRecordDao.findByOrderNo(orderNo);
        for (OrderItem orderItem : list) {
            OrderItemProductionRecordVo vo = new OrderItemProductionRecordVo();
            vo.setOrderNo(orderItem.getOrderNo());
            vo.setNumber(orderItem.getNumberStart());
            vo.setSpecs(orderItem.getSpecs());
            vo.setProduction(production);
            vo.setRoughSupplier(orderItem.getRoughSupplier());
            vo.setRoughItemNo(orderItem.getRoughItemNo());
            // 查询整个订单规格的工艺
            ProductionRecord productionRecord = getProductionRecord(productionRecords, orderNo, vo.getNumber(), production);
            // 获取其上一工序的记录
            String lastProduction = productionService.lastProduction(orderNo, orderItem.getSpecs(), production);
            ProductionRecord lastProductionRecord = getProductionRecord(productionRecords, orderNo, vo.getNumber(), lastProduction);
            if (lastProductionRecord != null) {
                if (StringUtil.isNotEmpty(lastProductionRecord.getEndTime())
                        && lastProductionRecord.getStatus().equals(Constant.PRODUCTION_RECORD_1) && (productionRecord == null || (productionRecord != null && StringUtil.isEmpty(
                        productionRecord.getEndTime())))) {
                    vo.setBackFlag("1");
                    vo.setReplenishmentFlag("1");
                }
            } else {
                vo.setReplenishmentFlag("1");
            }
            if (Objects.isNull(productionRecord)) {
                vo.setStatusDesc("未开始");
            } else {
                vo.setStartTime(productionRecord.getStartTime());
                vo.setEndTime(productionRecord.getEndTime());
                vo.setStaffName(productionRecord.getStaffName());
                vo.setStaffNumber(productionRecord.getStaffNumber());
                vo.setStaffId(productionRecord.getStaffId());
                vo.setStatus(productionRecord.getStatus());
                vo.setNgTag(productionRecord.getNgTag());
                if (StringUtil.equals(productionRecord.getStatus(), Constant.PRODUCTION_RECORD_5)) {
                    vo.setStatusDesc("已完成");
                }
                else if (StringUtil.equals(productionRecord.getStatus(), Constant.PRODUCTION_RECORD_2)) {
                    vo.setStatusDesc("补料申请中");
                } else if (StringUtil.equals(productionRecord.getStatus(), Constant.PRODUCTION_RECORD_1)) {
                    if (StringUtil.isNotEmpty(vo.getStartTime()) && StringUtil.isNotEmpty(vo.getEndTime())) {
                        vo.setStatusDesc("已完成");
                    } else {
                        vo.setStatusDesc("加工中");
                    }
                }
            }
            voList.add(vo);
        }
        map.put("list", voList);
        return map;
    }


    public List <OrderItem> pageOrderItem(List <OrderItem> list, String number, String specs, int pageNo, int pageSize) {
        if (list == null && list.size() == 0) {
            return new ArrayList <>();
        }
        // 只有一页
        if (list.size() < pageSize || list.size() == pageSize) {
            return list;
        }
        int fromIndex = ((pageNo - 1) * pageSize) - 1;
        fromIndex = fromIndex < 0 ? 0 : fromIndex;
        int toIndex = ((pageNo) * pageSize) - 1;
        toIndex = toIndex > list.size() - 1 ? list.size() - 1 : toIndex;

        return list.subList(fromIndex, toIndex);
    }

    private ProductionRecord getProductionRecord(List <ProductionRecord> productionRecords, String orderNo, String number, String production) {

        for (ProductionRecord productionRecord : productionRecords) {
            if (productionRecord.getOrderNo().equals(orderNo) && productionRecord.getNumber().equals(number)
                    && productionRecord.getProduction().equals(production)) {
                return productionRecord;
            }
        }
        return null;
    }

    // 查询定向下某个工艺的所有模具编号
    public List <OrderItem> listOrderItemByOrderNoAndProduction(String orderNo, String production) {
        List <OrderItem> result = new ArrayList <>();
        List <OrderItem> list = orderItemDao.listOrderItemByOrderNoAndProduction(orderNo, "%" + production + "%");
        for (OrderItem item : list) {
            int amount = Integer.parseInt(item.getAmount());
            String numberStart = item.getNumberStart();
            for (int k = 0; k < amount; k++) {
                OrderItem newItem = new OrderItem();
                BeanUtil.copyProperties(item, newItem);
                newItem.setNumberStart(numberStart + "");
                newItem.setNumberEnd(numberStart + "");
                numberStart = NumberUtil.nextNumber(numberStart);
                result.add(newItem);
            }
        }
        // 按磨具编号排序
        result = result.stream().sorted(Comparator.comparing(OrderItem::getSpecs)).
                collect(Collectors.toList());
        return result;
    }

    public List <String> getOrderItemList(String str, int num) {
        List <String> result = new ArrayList <>();
        //将字符串进行分类
        //收尾包含字母
        String numberStr = "";
        List <Item> list = new ArrayList <>();
        for (int i = 0; i < str.length(); i++) {
            if (!StringUtil.isNum(str.substring(i, i + 1))) {
                Item item = new Item();
                item.index = i;
                item.name = str.substring(i, i + 1);
                System.out.println(JSON.toJSON(item));
                list.add(item);
            } else {
                numberStr = numberStr + str.substring(i, i + 1);
            }
        }

        if (str.contains("-")) {
            numberStr = str.split("-")[1];
            Item item = new Item();
            item.name = str.split("-")[0] + "-";
            item.index = 0;
            list = new ArrayList <>();
            list.add(item);
        }
        for (int i = 0; i < num; i++) {
            Integer n = Integer.parseInt(numberStr);
            String s = returnStr(n + i, list);
            result.add(s);
        }
        return result;
    }


    private String returnStr(Integer n, List <Item> list) {
        int length = (n + "").length();
        String str = n + "";
        for (Item item : list) {
            if (item.index < length) {
                str = item.name + str;
            } else {
                str = str + item.name;
            }
        }
        return str;
    }


    private class Item {
        public int index;
        public String name;
    }


    // 工艺退回   如果backProduction==null 则退回上一工艺 否则就是退回指定的工艺
    public MessageResult back(String orderNo, String number, String specs, String backProduction) {
        // 查询当前订单模具的流转工艺
        List <String> productions = productionService.productions(orderNo, specs);
        String finalProduction = productions.get(productions.size() - 1);

        String time = DateUtil.getFormatedDateTime();
        int num = 0;
        boolean flag = false;
        // backProduction 多个工艺逗号分割 只回退指定的工艺
        if (StringUtil.isNotEmpty(backProduction)) {
            // 品管回退  回退指定的工艺
            /**
             * 1、逻辑梳理：
             *   查询回退最前的工艺，然后将后面的工艺赋予
             */
            String firstProduction = "";
            List <String> list4 = new ArrayList <>();
            List <String> list5 = new ArrayList <>();
            boolean addFlag = false;
            for (String s : productions) {
                if (backProduction.contains(s)) {
                    if (StringUtil.isEmpty(firstProduction)) {
                        firstProduction = s;
                    }
                    addFlag = true;
                }
                if (addFlag) {
                    if (backProduction.contains(s)) {
                        list4.add(s);
                    } else {
                        if (finalProduction.equals(s)) {
                            list4.add(s);
                        } else {
                            list5.add(s);
                        }

                    }
                }
            }
            List <ProductionRecord> productionRecords5 = productionRecordDao.
                    findByOrderNoAndNumberAndStatusAndProductionIn(orderNo, number, Constant.PRODUCTION_RECORD_1, list5);
            for (ProductionRecord productionRecord : productionRecords5) {
                productionRecord.setStatus(Constant.PRODUCTION_RECORD_5);
//                productionRecord.setStatus(Constant.PRODUCTION_RECORD_1);
                productionRecord.setRemark("品管回退跳过记录");
            }
            productionRecordDao.saveAll(productionRecords5);


            // 将回退到的指定工艺 也置位4的状态
            ProductionRecord firstProductionRecord = productionRecordDao.findTopByOrderNoAndNumberAndProductionAndStatusOrderByIdDesc(orderNo, number, firstProduction, Constant.PRODUCTION_RECORD_1);

            List <ProductionRecord> productionRecords4 = productionRecordDao.
                    findByOrderNoAndNumberAndStatusAndProductionIn(orderNo, number, Constant.PRODUCTION_RECORD_1, list4);
            if (firstProductionRecord != null) {
                productionRecords4.add(firstProductionRecord);
            }


            for (ProductionRecord productionRecord : productionRecords4) {
                productionRecord.setStatus(Constant.PRODUCTION_RECORD_4);
                productionRecord.setRemark("回退记录（品管）");
            }
            productionRecordDao.saveAll(productionRecords4);

            // 回退到指定工艺的时候  需要做开始工艺 所以不需要系统自动执行开始工艺
//            ProductionRecord newProductionRecord = new ProductionRecord();
//            BeanUtil.copyProperties(firstProductionRecord, newProductionRecord);
//            newProductionRecord.setId(null);
//            newProductionRecord.setStatus(Constant.PRODUCTION_RECORD_1);
//            newProductionRecord.setEndTime(null);
//            newProductionRecord.setRemark("回退记录");
//            newProductionRecord.setCreateTime(DateUtil.getFormatedDateTime());
//            productionRecordDao.save(newProductionRecord);
        }
        //普通工艺的回退
        else {
            List <ProductionRecord> list = new ArrayList <>();
            ProductionRecord productionRecord = productionRecordDao.findTopByOrderNoAndNumberAndStatusOrderByIdDesc(orderNo, number, Constant.PRODUCTION_RECORD_1);
            if (Objects.isNull(productionRecord)) {
                return MessageResult.error("未找到当前产品流转记录");
            }
            productionRecord.setUpdateTime(time);
            productionRecord.setStatus(Constant.PRODUCTION_RECORD_4);
            list.add(productionRecord);
            // 查询其流转工艺模板
            String lastProduction = queryLastProductionRecord(productionRecord);
            ProductionRecord lastProductionRecord = productionRecordDao.findTopByOrderNoAndNumberAndProductionAndStatusOrderByIdDesc(orderNo, number, lastProduction, Constant.PRODUCTION_RECORD_1);
            ProductionRecord newProductionRecord = new ProductionRecord();
            BeanUtil.copyProperties(lastProductionRecord, newProductionRecord);
            newProductionRecord.setId(null);
            newProductionRecord.setStatus(Constant.PRODUCTION_RECORD_1);
            newProductionRecord.setEndTime(null);
            newProductionRecord.setRemark("回退记录");
            newProductionRecord.setCreateTime(DateUtil.getFormatedDateTime());
            lastProductionRecord.setUpdateTime(time);
            lastProductionRecord.setStatus(Constant.PRODUCTION_RECORD_4);
            // 回退的时候不能使用之前的开始工艺时间 需要重新做开始工艺
            // list.add(newProductionRecord);
            list.add(lastProductionRecord);
            productionRecordDao.saveAll(list);
        }
        return MessageResult.success();
    }


    // 工艺退回   如果backProduction==null 则退回上一工艺 否则就是退回指定的工艺

    /*
    *
    * *****************  备份  *************************
     public MessageResult back(String orderNo, String number, String specs, String nowProduction, String backProduction) {
     // 查询当前订单模具的流转工艺
     List<String> productions = productionService.productions(orderNo, specs);
     String time = DateUtil.getFormatedDateTime();
     int num = 0;
     boolean flag = false;
     // backProduction 多个工艺逗号分割 只回退指定的工艺
     if (StringUtil.isNotEmpty(backProduction)) {
     for (String s : productions) {
     if (StringUtil.equals(backProduction, s)) {
     flag = true;
     }
     if (s.equals(nowProduction)) {
     break;
     }
     if (flag) {
     num++;
     }
     }
     } else {
     num = 1;
     }

     for (int i = 0; i < num; i++) {
     List<ProductionRecord> list = new ArrayList<>();
     ProductionRecord productionRecord = productionRecordDao.findTopByOrderNoAndNumberAndStatusOrderByIdDesc(orderNo, number, Constant.PRODUCTION_RECORD_1);
     if (Objects.isNull(productionRecord)) {
     return MessageResult.error("未找到当前产品流转记录");
     }

     productionRecord.setUpdateTime(time);
     productionRecord.setStatus(Constant.PRODUCTION_RECORD_4);
     list.add(productionRecord);
     // 查询其流转工艺模板
     String lastProduction = queryLastProductionRecord(productionRecord);
     ProductionRecord lastProductionRecord = productionRecordDao.findTopByOrderNoAndNumberAndProductionAndStatusOrderByCreateTimeDesc(orderNo, number, lastProduction, Constant.PRODUCTION_RECORD_1);
     ProductionRecord newProductionRecord = new ProductionRecord();
     BeanUtil.copyProperties(lastProductionRecord, newProductionRecord);
     newProductionRecord.setId(null);
     newProductionRecord.setStatus(Constant.PRODUCTION_RECORD_1);
     newProductionRecord.setEndTime(null);
     newProductionRecord.setRemark("回退记录");
     newProductionRecord.setCreateTime(DateUtil.getFormatedDateTime());
     lastProductionRecord.setUpdateTime(time);
     lastProductionRecord.setStatus(Constant.PRODUCTION_RECORD_4);
     list.add(newProductionRecord);
     list.add(lastProductionRecord);
     productionRecordDao.saveAll(list);
     }
     return MessageResult.success();
     }
     */

    // 获取其上一个工艺
    public String queryLastProductionRecord(ProductionRecord productionRecord) {
        Production production = productionDao.findTopByOrderNoAndSpecs(productionRecord.getOrderNo(), productionRecord.getSpecs());
        if (Objects.isNull(production) || Objects.isNull(production.getProcedures())) {
            throw new BusinessException("请检查该订单参数表是否已上传");
        }
        List <String> list = (List) JSONUtils.parse(production.getProcedures());
        for (int i = 0; i < list.size(); i++) {
            if (StringUtil.equals(productionRecord.getProduction(), list.get(i))) {
                if (i == 0) {
                    return list.get(0);
                } else {
                    return list.get(i - 1);
                }
            }
        }
        throw new BusinessException(Constant.DATA_ERROR);
    }

    public List <OrderProductionRecordVo> queryOrderItemProductionRecord(String orderNo, String number, String specs) {
        Production production = productionDao.findTopByOrderNoAndSpecs(orderNo, specs);
        if (Objects.isNull(production) || Objects.isNull(production.getProcedures())) {
            throw new BusinessException("请检查该订单参数表是否已上传");
        }
        List <String> list = (List) JSONUtils.parse(production.getProcedures());
        List <OrderProductionRecordVo> voList = new ArrayList <>();
        for (int i = 0; i < list.size(); i++) {
            String procedure = list.get(i);
            OrderProductionRecordVo vo = new OrderProductionRecordVo();
            ProductionRecord productionRecord = productionRecordDao.findTopByOrderNoAndNumberAndProductionAndStatusOrderByIdDesc(orderNo, number, procedure, Constant.PRODUCTION_RECORD_1);
            vo.setSeque(i + 1);
            vo.setProduction(procedure);
            vo.setOrderNo(orderNo);
            if (Objects.isNull(productionRecord)) {
                vo.setStatus(Constant.PRODUCTION_RECORD_0);
            } else {
                if (StringUtil.isNotEmpty(productionRecord.getStartTime())) {
                    vo.setStartTime(productionRecord.getStartTime().substring(11, 16));
                }
                if (StringUtil.isNotEmpty(productionRecord.getEndTime())) {
                    vo.setEndTime(productionRecord.getEndTime().substring(11, 16));
                }
                if (Objects.nonNull(vo.getStartTime()) && Objects.nonNull(vo.getEndTime())) {
                    vo.setStatus(Constant.PRODUCTION_RECORD_2);
                } else if (Objects.nonNull(vo.getStartTime()) && Objects.isNull(vo.getEndTime())) {
                    vo.setStatus(Constant.PRODUCTION_RECORD_1);
                }
            }
            voList.add(vo);
        }
        return voList;
    }


    // 查询可以执行production工艺的模具编号
    // 只有修理品订单才会调用
    public String queryUpdateOrderNumber(String orderNo, String specs, String production, String ngTag) {
        // 1、判断production 是包含开始 还是结束
        // 如果是开始 则需要查找其上一个工序的名称
        if (production.contains(Constant.PRODUCTION_RECORD_TAG_START)) {
            production = production.split("-")[0];
            List <String> list = productionService.productions(orderNo, specs);
            for (int i = 0; i < list.size(); i++) {
                if (StringUtil.equals(list.get(i), production)) {
                    OrderItem orderItem = orderItemDao.findTopByOrderNoAndSpecs(orderNo, specs);
                    if (i == 0) {
                        // 直接去orderItem取一个数据
                        int amount = Integer.parseInt(orderItem.getAmount());
                        List <ProductionRecord> productionRecords = productionRecordDao.countByOrderNoAndSpecsAndProductionOrderByNumberDesc(orderNo, specs, production, null);
                        if (productionRecords.size() >= amount) {
                            throw new BusinessException("无法进行该工艺流转，请先查看订单流转详情");
                        }
                        if (productionRecords.size() == 0) {
                            return orderItem.getNumberStart();
                        }
                        List <String> list2 = productionRecords.stream().map(bean -> bean.getNumber()).collect(Collectors.toList());

                        for (int k = Integer.parseInt(orderItem.getNumberStart()); k <= Integer.parseInt(orderItem.getNumberEnd()); k++) {
                            if (!list2.contains(k + "")) {
                                return k + "";
                            }
                        }
                        throw new BusinessException("未找到符合要求的模具编号");
                    } else {
                        //TODO  先查询本工序已使用最大的number  然后查询上一工序使用的number
                        OrderItem orderItem2 = orderItemDao.findTopByOrderNoAndSpecs(orderNo, specs);
                        // productionRecords1 一定不会为空 productionRecords2可能为空
                        List <ProductionRecord> productionRecords1 = productionRecordDao.countByOrderNoAndSpecsAndProductionAndEndTimeNotNullOrderByNumberDesc(orderNo, specs, list.get(i - 1), ngTag);

                        List <ProductionRecord> productionRecords2 = productionRecordDao.countByOrderNoAndSpecsAndProductionOrderByNumberDesc(orderNo, specs, list.get(i), null);
//                        if (productionRecords.size() == 0) {
//                            productionRecords = productionRecordDao.countByOrderNoAndSpecsAndProductionOrderByNumberDesc(orderNo, specs, list.get(i - 1));
//                        }
                        //获取已使用的最大模具编号
                        // 如果productionRecords2为空  则从上一工序中使用的编码中取一个
                        if (productionRecords2.size() == 0) {
                            return productionRecords1.get(0).getNumber();
                        }
                        List <String> list2 = productionRecords2.stream().map(bean -> bean.getNumber()).collect(Collectors.toList());
                        for (ProductionRecord p : productionRecords1) {
                            if (!list2.contains(p.getNumber())) {
                                return p.getNumber();
                            }
                        }

                        productionRecords1 = productionRecordDao.countByOrderNoAndSpecsAndProductionAndEndTimeNotNullOrderByNumberDesc(orderNo, specs, list.get(i - 1), "0");

                        if (productionRecords2.size() == 0) {
                            return productionRecords1.get(0).getNumber();
                        }
                        for (ProductionRecord p : productionRecords1) {
                            if (!list2.contains(p.getNumber())) {
                                return p.getNumber();
                            }
                        }
                        throw new BusinessException("未找到符合要求的模具编号");

                    }
                }
            }
            throw new BusinessException("数据异常，请先查看订单流转详情");
        } else {
            production = production.split("-")[0];
            List <ProductionRecord> productionRecords = productionRecordDao.queryByOrderNoAndSpecsAndProductionOrderByNumberAsc(orderNo, specs, production, ngTag);
            if (productionRecords.size() == 0) {
                // 如果为空  且ngTag==1 则需要去查找正常的 即ngtag=0再去查找一次 如果为空 则
                if (ngTag.equals("1")) {
                    productionRecords = productionRecordDao.queryByOrderNoAndSpecsAndProductionOrderByNumberAsc(orderNo, specs, production, "0");
                    if (productionRecords.size() == 0) {
                        throw new BusinessException("无法进行该工艺流转，请先查看订单流转详情");
                    }
                    ProductionRecord productionRecord = productionRecords.get(0);
                    productionRecord.setNgTag("1");
                    productionRecordDao.save(productionRecord);
                    return productionRecord.getNumber();
                }


            }
            return productionRecords.get(0).getNumber();
        }
    }


    public MessageResult listStaffProductionRecord(String orderNo, String staffNumber, String startTime, String endTime, String production, String status, int pageNo, int pageSize) {
        String startDate = null;
        String endDate = null;
        if (StringUtil.isNotEmpty(startTime) && StringUtil.isNotEmpty(endTime)) {
            startDate = startTime.substring(0, 10);
            endDate = endTime.substring(0, 10);
        }

        long t1 = System.currentTimeMillis();
        long total = productionRecordDao.countStaffProductionRecord(orderNo, staffNumber, startDate, endDate, production, status);
        long t2 = System.currentTimeMillis();
        System.out.println("查询数量用时：" + (t2 - t1));
        MessageResult mr = MessageResult.success();
        if (total == 0) {
            return mr;
        }
        t1 = System.currentTimeMillis();
        List <Map <String, Object>> mapList = productionRecordDao.listStaffProductionRecord(orderNo, staffNumber, startDate, endDate, production, status, (pageNo - 1) * pageSize
                , pageSize);
        t2 = System.currentTimeMillis();
        System.out.println("查询信息用时：" + (t2 - t1));
        List <Map <String, Object>> newMapList = new ArrayList <>();
        for (Map <String, Object> map : mapList) {
            // 查询该员工某个这个工序的最先的开始时间 和最后的结束时间
            Map <String, Object> newMap = new HashMap <>(map);
            String timeStatus = MapUtil.getStringValue(map, "status");

            Long staff_id = MapUtil.getLongValue(map, "staff_id");
            String order_no = MapUtil.getStringValue(map, "order_no");
            String specs = MapUtil.getStringValue(map, "specs");
            OrderItem orderItem = orderItemDao.findTopByOrderNoAndSpecs(order_no, specs);
            if (orderItem != null) {
                newMap.put("roughSupplier", orderItem.getRoughSupplier());
                newMap.put("roughItemNo", orderItem.getRoughItemNo());
                newMap.put("compressUp2", orderItem.getCompressUp2());
                newMap.put("compressDown2", orderItem.getCompressDown2());
                newMap.put("dingjingUp2", orderItem.getDingjingUp2());
                newMap.put("dingjingDown2", orderItem.getDingjingDown2());
                newMap.put("custNo", orderItem.getCustNo());
            }
            // 已完工 结束时间不为空
//            Map<String, Object> timeMap = new HashMap<>();
//            if ("1".equals(timeStatus)) {
//                timeMap = productionRecordDao.queryProductionRecordStartTimeAndEndTime(MapUtil.getStringValue(map, "order_no"), MapUtil.getStringValue(map, "specs")
//                        , MapUtil.getStringValue(map, "production"));
//                String start_time = MapUtil.getStringValue(timeMap, "start_time");
//                String end_time = MapUtil.getStringValue(timeMap, "end_time");
//                newMap.put("startTime", start_time);
//                newMap.put("endTime", end_time);
//                //计算工作时间
//                newMap.put("subTime", DateUtil.getDateDesc(start_time, end_time));
//            } else {
//                timeMap = productionRecordDao.queryProductionRecordStartTime(MapUtil.getStringValue(map, "order_no"), MapUtil.getStringValue(map, "specs")
//                        , MapUtil.getStringValue(map, "production"));
//                newMap.put("startTime", MapUtil.getStringValue(timeMap, "start_time"));
//                newMap.put("endTime", "");
//                //计算工作时间
//                newMap.put("subTime", "");
//            }

            //查询员工信息
            Staff staff = staffDao.findById(staff_id).orElse(null);
            if (staff != null) {
                newMap.put("staff_name", staff.getName());
                newMap.put("staff_number", staff.getNumber());
            }
            newMapList.add(newMap);
        }

        mr.setTotal(total);
        mr.setTotalElement(newMapList);
        return mr;
    }


    public List <ProductionRecord> listWorkDoneProductionRecord(String orderNo, String specs, String production, String staffNumber) {
        return productionRecordDao.listWorkDoneProductionRecord(orderNo, specs, production, staffNumber);
    }

    public ProductionRecord queryOne(String orderNo, String number, String production) {
        return productionRecordDao.findTopByOrderNoAndNumberAndProductionAndStatusAndEndTimeNotNull(orderNo, number, production, Constant.STATUS_1);
    }

    // 查询某个规格 某个工艺待流转的数量
    public Map <String, Object> toBeTransferredNum(String orderNo, String specs, String productionTag) {
        Map <String, Object> map = new HashMap <>();
        String production = productionTag.split("-")[0];
        // 如果是查询某个工序的开始  则用上一工序已完成的数量 减去本工序已完成的数量
        //  NG的数量 最少不能少于上一工序的数量 最大不能大于总数
        if (productionTag.contains(Constant.PRODUCTION_RECORD_TAG_START)) {
            String last = productionService.lastProduction(orderNo, specs, production);
            // 操作的正好是第一个工序
            int total = 0;
            int startNum = 0;
            if (last.equals(production)) {
                total = productionDao.querySpecsProductionAmount(orderNo, specs, "%" + last + "%");
                startNum = productionDao.querySpecsProductionToBeAmount(orderNo, specs, production, "true", null, null);
                map.put("ngNum", total - startNum);
                map.put("okNum", total - startNum);
                map.put("lastNgNum", 0);
                map.put("ngCheck", "false");
                map.put("totalCheck", "false");
            } else {
                //  如果操作的不是第一个工序 则需要查询上一工序NG的数量  和本工序的总数量和本工序已开始的数量 然后NG数量最小不能少于 上一工序减去已开始的数量
                //  最大不能大于 总数量减去已开始的数量
                //  本工序的总数量
                // OK的数量 不能大于
                //计算出NG最少的数量  OK的数量 不能大于此数量
                int total1 = productionDao.querySpecsProductionAmount(orderNo, specs, "%" + production + "%");
                // 本工序已开始的数量
                int startNum1 = productionDao.querySpecsProductionToBeAmount(orderNo, specs, production, "true", null, null);
                // 上一工序NG的数量
                int lastStartNum = productionDao.querySpecsProductionToBeAmount(orderNo, specs, last, "true", null, "1");
                // 本工序已开始的NG数量
                startNum = productionDao.querySpecsProductionToBeAmount(orderNo, specs, production, "true", null, "1");

                if (startNum > lastStartNum) {
                    map.put("okNum", total1 - startNum1);
                    map.put("ngNum", total1 - startNum1);
                    map.put("ngCheck", "false");
                } else {
                    map.put("ngCheck", "true");
                    map.put("okNum", total1 - startNum1 - (lastStartNum - startNum));
                    map.put("ngNum", total1 - startNum1);
                    map.put("totalCheck", "true");
                    map.put("totalNum", total1 - startNum1);
                }
            }
            return map;
        }

        //  结束的时候 即使开始没有ng数量 结束的时候也可以弄成NG
        else {
            // 查询当前工序已经OK开始的数量
            int startNum = productionDao.querySpecsProductionToBeAmount(orderNo, specs, production, "true", null, "0");
            // 查询当前工序已经OK完成的
            int endNum = productionDao.querySpecsProductionToBeAmount(orderNo, specs, production, null, "true", "0");
            // ok不能超过的数量
            int okNum = startNum - endNum;
            startNum = productionDao.querySpecsProductionToBeAmount(orderNo, specs, production, "true", null, null);
            endNum = productionDao.querySpecsProductionToBeAmount(orderNo, specs, production, null, "true", null);
            int ngNum = startNum - endNum;
            map.put("ngNum", ngNum);
            map.put("okNum", okNum);
            map.put("ngCheck", "true");
            map.put("totalCheck", "true");
            map.put("totalNum", startNum - endNum);
            return map;
        }

    }

    public Map <String, Object> subNum(String orderNo, String production) {
        Set <Map <String, Object>> result = new LinkedHashSet <>();
        List <Map <String, Object>> mapList = productionRecordDao.subNum(orderNo, production);
        InsideOrder insideOrder = insideOrderService.queryInsideOrderByOrderNo(orderNo);
        Map <String, Map <String, Object>> filterMap = new HashMap <>();
        List <String> addList = new ArrayList <>();
        for (Map <String, Object> map : mapList) {
            String specs = MapUtil.getStringValue(map, "s");
            BigInteger num = (BigInteger) map.get("num");
            String ngTag = MapUtil.getStringValue(map, "ng_tag");
            String total = MapUtil.getStringValue(map, "total");
            Map <String, Object> temp = null;
            if (filterMap.containsKey(specs)) {
                temp = filterMap.get(specs);
            } else {
                temp = new HashMap <>();
                temp.put("specs", specs);
                temp.put("okNum", 0);
                temp.put("total", total);
                temp.put("ngNum", 0);
            }
            //如果是新品订单 则需要查询某个规格的补料申请数量
            String type = insideOrder.getType();
            temp.put("type", type);
            if ("N".equals(type)) {
                int replenishmentCount = replenishmentDao.queryReplenishmentCount(orderNo, specs, production);
                temp.put("replenishmentCount", replenishmentCount);
            }
            if ("0".equals(ngTag)) {
                temp.put("okNum", num);
            } else {
                temp.put("ngNum", num);
            }
            filterMap.put(specs, temp);
            if (!addList.contains(specs)) {
                result.add(temp);
                addList.add(specs);
            }

        }
        Map <String, Object> map = new HashMap <>();
        map.put("list", result);
        map.put("type", insideOrder.getType());
        return map;
    }
}
